package server

import (
	"context"
	"errors"
	"fmt"
	"go_iot/pkg/global"
	"net"
	"sync"
	"syscall"
	"time"
)

const readBufferSize = 1024

var wg sync.WaitGroup
var ctx context.Context
var cancel context.CancelFunc

type ServerTcp struct {
	listen net.Listener
	ctx    context.Context
	cancel context.CancelFunc
}

func NewServer(address string) (*ServerTcp, error) {
	// 设置TCP参数优化
	lc := net.ListenConfig{
		Control: func(network, address string, c syscall.RawConn) error {
			return c.Control(func(fd uintptr) {
				// 设置SO_REUSEADDR
				syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
			})
		},
		KeepAlive: 30 * time.Second,
	}

	ctx, cancel = context.WithCancel(context.Background())
	l, err := lc.Listen(ctx, "tcp", address)

	return &ServerTcp{
		listen: l,
		ctx:    ctx,
		cancel: cancel,
	}, err

}

func (s *ServerTcp) Start() {
	global.Log.Info("tcp服务启动")

	for {
		conn, err := s.listen.Accept()
		if err != nil {
			if errors.Is(err, net.ErrClosed) {
				return
			}
			continue
		}
		select {
		case <-s.ctx.Done():
			return
		default:
			go handleConn(conn)
		}

	}

}

func (s *ServerTcp) Stop() {
	s.listen.Close()
	s.cancel()
	wg.Wait()
	global.Log.Info("tcp服务关闭")
}

func handleConn(conn net.Conn) {
	defer func() {
		conn.Close()
		wg.Done()
	}()
	wg.Add(1)
	conn.SetReadDeadline(time.Now().Add(5 * time.Second))

	b := make([]byte, readBufferSize)

	_, err := conn.Read(b)
	if err != nil {
		fmt.Println("有错误：" + err.Error())
		return
	}

	for {
		conn.SetReadDeadline(time.Now().Add(125 * time.Second))
		i, err := conn.Read(b)
		if err != nil {
			fmt.Println("有错误：" + err.Error())
			return
		}
		select {
		case <-ctx.Done():
			return
		default:
			fmt.Println(string(b[:i]))
		}

	}
}
